package com.example.demo.service.impl;

import com.example.demo.entity.CopyrightEntity;
import com.example.demo.entity.CopyrightTransferEntity;
import com.example.demo.model.CopyrightInfo;
import com.example.demo.model.CopyrightTransferInfo;
import com.example.demo.repository.CopyrightRepository;
import com.example.demo.repository.CopyrightTransferRepository;
import com.example.demo.service.AccountService;
import com.example.demo.service.BlockchainService;
import com.example.demo.service.CopyrightService;
import com.example.demo.synchronizer.CopyrightDataSynchronizer;
import com.example.demo.utils.CopyrightUtils;
import com.example.demo.validator.CopyrightValidator;
import lombok.extern.slf4j.Slf4j;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.model.TransactionReceipt;
import org.fisco.bcos.sdk.transaction.model.dto.CallResponse;
import org.fisco.bcos.sdk.transaction.model.dto.TransactionResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 版权服务实现类，提供版权创建、转移和查询功能
 */
@Slf4j
@Service
public class CopyrightServiceImpl implements CopyrightService {
    
    @Resource
    private Client client;
    
    @Autowired
    private AccountService accountService;
    
    @Autowired
    private CopyrightRepository copyrightRepository;
    
    @Autowired
    private CopyrightTransferRepository transferRepository;
    
    // 注入新的服务
    @Autowired
    private BlockchainService blockchainService;
    
    @Autowired
    private CopyrightValidator copyrightValidator;
    
    @Autowired
    private CopyrightDataSynchronizer dataSynchronizer;
    
    // 图片存储目录
    @Value("${copyright.upload.dir:uploads}")
    private String uploadDirectory;
    
    private TransactionReceiptListener receiptListener;
    
    @PostConstruct
    public void init() {
        log.info("初始化版权服务实现类...");
        try {
            // 初始化上传目录，确保图片存储的基础目录存在
            CopyrightUtils.initUploadDirectory();
            log.info("版权服务初始化完成");
        } catch (Exception e) {
            log.error("版权服务初始化失败: {}", e.getMessage(), e);
            throw new RuntimeException("版权服务初始化失败: " + e.getMessage(), e);
        }
    }
    
    @Override
    public void addTransactionReceiptListener(TransactionReceiptListener listener) {
        this.receiptListener = listener;
        // 委托给区块链服务处理底层监听器逻辑，并在收到回调时触发本地监听器
        blockchainService.addTransactionReceiptListener(receipt -> {
            if (receiptListener != null) {
                receiptListener.onReceipt(receipt);
            }
        });
    }
    
    @Override
    public void removeTransactionReceiptListener() {
        this.receiptListener = null;
        blockchainService.removeTransactionReceiptListener();
    }
    
    /**
     * 创建版权的内部辅助方法
     */
    private BigInteger createCopyrightInternal(String address, String imageHash) {
        log.info("创建版权: 所有者={}, 图片哈希={}", address, imageHash);
        
        // 参数验证
        if (!copyrightValidator.isValidAddressFormat(address)) {
            throw new IllegalArgumentException("地址格式不正确");
        }
        if (imageHash == null || imageHash.isEmpty()) {
            throw new IllegalArgumentException("图片哈希不能为空");
        }
        
        try {
            // 准备合约调用参数
            List<Object> params = new ArrayList<>();
            params.add(imageHash);
            
            // 发送合约交易 - 调用区块链服务执行实际的智能合约调用
            TransactionResponse response = blockchainService.sendTransaction(
                "createCopyright", 
                params, 
                address
            );
            
            // 解析返回值 - 从交易响应中提取版权ID
            BigInteger copyrightId = blockchainService.parseReturnBigInteger(response);
            if (copyrightId == null) {
                throw new IllegalArgumentException("创建版权失败，无法获取版权ID");
            }
            
            // 同步数据到数据库 - 将区块链上的创建信息同步到本地数据库
            dataSynchronizer.syncCopyrightCreation(
                copyrightId,
                imageHash,
                address,
                response.getTransactionReceipt().getTransactionHash()
            );
            
            return copyrightId;
        } catch (Exception e) {
            log.error("创建版权异常: {}", e.getMessage(), e);
            throw new RuntimeException("创建版权失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 转移版权的内部辅助方法
     */
    private void transferCopyrightInternal(String address, BigInteger copyrightId, String to) {
        log.info("转让版权: 所有者={}, 版权ID={}, 接收者={}", address, copyrightId, to);
        
        // 校验参数
        if (!copyrightValidator.isValidAddressFormat(address) || 
            !copyrightValidator.isValidAddressFormat(to)) {
            throw new IllegalArgumentException("地址格式不正确");
        }
        
        if (!copyrightValidator.isValidTransferAddresses(address, to)) {
            throw new IllegalArgumentException("不能将版权转让给自己");
        }
        
        try {
            // 验证版权所有权 - 确保调用方确实是版权的所有者
            copyrightValidator.validateCopyrightOwnership(copyrightId, address);
            
            // 准备合约调用参数
            List<Object> params = new ArrayList<>();
            params.add(copyrightId);
            params.add(to);
            
            // 发送合约交易 - 调用区块链服务执行实际的智能合约调用
            TransactionResponse response = blockchainService.sendTransaction(
                "transferCopyright", 
                params, 
                address
            );
            
            // 获取交易收据
            TransactionReceipt receipt = response.getTransactionReceipt();
            String txHash = receipt.getTransactionHash();
            log.info("版权转让交易哈希: {}", txHash);
            
            // 同步链上所有权变更到数据库 - 更新本地数据库中的所有者信息
            dataSynchronizer.syncOwnershipChange(copyrightId, to);
            
            // 记录转让历史 - 在数据库中创建转让记录
            Long dbId = dataSynchronizer.findDatabaseIdByBlockchainId(copyrightId.toString());
            if (dbId != null) {
                dataSynchronizer.recordTransferHistory(dbId, address, to, txHash);
            }
        } catch (Exception e) {
            log.error("转让版权异常: {}", e.getMessage(), e);
            throw new RuntimeException("转让版权失败: " + e.getMessage(), e);
        }
    }
    
    @Override
    public CopyrightInfo transferCopyright(String copyrightId, String fromAddress, String toAddress) {
        log.info("转移版权: ID={}, 从{}到{}", copyrightId, fromAddress, toAddress);
        
        // 校验参数
        if (copyrightId == null || copyrightId.isEmpty()) {
            throw new IllegalArgumentException("版权ID不能为空");
        }
        
        // 校验地址格式 - 验证发送方和接收方的地址是否符合格式要求
        if (!copyrightValidator.isValidAddressFormat(fromAddress) || 
            !copyrightValidator.isValidAddressFormat(toAddress)) {
            throw new IllegalArgumentException("地址格式不正确");
        }
        
        // 检查不能转让给自己 - 验证发送方和接收方不是同一地址
        if (!copyrightValidator.isValidTransferAddresses(fromAddress, toAddress)) {
            throw new IllegalArgumentException("不能将版权转让给自己");
        }
        
        try {
            // 将版权ID转换为BigInteger
            BigInteger id = new BigInteger(copyrightId);
            
            // 使用内部方法进行转移操作 - 调用私有辅助方法处理核心转移逻辑
            transferCopyrightInternal(fromAddress, id, toAddress);
            
            // 获取更新后的版权信息 - 从数据库获取最新的版权信息
            CopyrightInfo info = dataSynchronizer.getCopyrightFromDB(id);
            log.info("版权转让完成: ID={}, 新所有者={}", copyrightId, toAddress);
            
            return info;
        } catch (IllegalArgumentException e) {
            // 重新抛出业务验证异常
            log.warn("版权转让业务验证失败: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("版权转让异常: {}", e.getMessage(), e);
            throw new RuntimeException("版权转让失败: " + e.getMessage(), e);
        }
    }
    
    @Override
    public CopyrightInfo getCopyright(BigInteger copyrightId) {
        if (copyrightId == null) {
            log.warn("版权ID为空");
            return null;
        }
        
        try {
            // 先尝试从数据库获取 - 优先使用本地数据库提高响应速度
            CopyrightInfo info = dataSynchronizer.getCopyrightFromDB(copyrightId);
            if (info != null) {
                return info;
            }
            
            // 从区块链获取 - 数据库没有找到时，查询区块链源数据
            List<Object> params = new ArrayList<>();
            params.add(copyrightId);
            
            CallResponse response = blockchainService.sendCall("getCopyright", params, null);
            
            if (response == null || response.getValues() == null || response.getValues().isEmpty()) {
                return null;
            }
            
            // 解析版权信息 - 将区块链返回的数据解析为结构化信息
            String[] parts = blockchainService.parseCopyrightInfo(response.getValues());
            if (parts.length < 5) {
                return null;
            }
            
            // 创建版权信息对象
            CopyrightInfo copyright = new CopyrightInfo();
            copyright.setBlockchainId(copyrightId.toString());
            copyright.setImageHash(parts[1]);
            copyright.setOwnerAddress(parts[2]);
            try {
                copyright.setCreateTime(new BigInteger(parts[3]));
            } catch (NumberFormatException e) {
                copyright.setCreateTime(BigInteger.ZERO);
            }
            copyright.setIsValid(Boolean.parseBoolean(parts[4]));
            
            return copyright;
        } catch (Exception e) {
            log.error("获取版权信息异常: {}", e.getMessage(), e);
            return null;
        }
    }
    
    @Override
    public List<BigInteger> getCopyrightsByOwner(String address) {
        if (address == null || address.isEmpty()) {
            return Collections.emptyList();
        }
        
        try {
            List<Object> params = new ArrayList<>();
            params.add(address);
            
            // 发送区块链调用 - 查询指定所有者的所有版权ID
            CallResponse response = blockchainService.sendCall("getCopyrightsByOwner", params, address);
            
            // 解析返回值数组 - 将返回的数据解析为BigInteger列表
            return blockchainService.parseReturnBigIntegerArray(response);
        } catch (Exception e) {
            log.error("获取所有者版权列表异常: {}", e.getMessage(), e);
            return Collections.emptyList();
        }
    }
    
    @Override
    public Client getClient() {
        return this.client;
    }
    
    @Override
    public List<CopyrightInfo> getCopyrightsByOwnerFromDB(String ownerAddress) {
        try {
            return copyrightRepository.findByOwnerAddressOrderByCreateTimeDesc(ownerAddress)
                    .stream()
                    .map(this::convertEntityToInfo)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("从数据库获取所有者版权列表异常: {}", e.getMessage(), e);
            return Collections.emptyList();
        }
    }
    
    @Override
    public List<CopyrightInfo> getCopyrightsByImageHashFromDB(String imageHash) {
        try {
            return copyrightRepository.findByImageHashOrderByCreateTimeDesc(imageHash)
                    .stream()
                    .map(this::convertEntityToInfo)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("从数据库获取图片哈希版权列表异常: {}", e.getMessage(), e);
            return Collections.emptyList();
        }
    }
    
    @Override
    public List<CopyrightInfo> getValidCopyrightsByOwnerFromDB(String ownerAddress) {
        try {
            return copyrightRepository.findByOwnerAddressAndIsValidTrueOrderByCreateTimeDesc(ownerAddress)
                    .stream()
                    .map(this::convertEntityToInfo)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("从数据库获取所有者有效版权列表异常: {}", e.getMessage(), e);
            return Collections.emptyList();
        }
    }
    
    @Override
    public CopyrightInfo convertEntityToInfo(CopyrightEntity entity) {
        if (entity == null) {
            return null;
        }
        
        // 创建并填充版权信息对象 - 将数据库实体转换为业务模型对象
        CopyrightInfo info = new CopyrightInfo();
        info.setId(entity.getId());
        info.setBlockchainId(entity.getBlockchainId());
        info.setImageHash(entity.getImageHash());
        info.setOwnerAddress(entity.getOwnerAddress());
        
        if (entity.getCreateTime() != null) {
            // 转换时间戳 - 将Java日期时间转换为以秒为单位的时间戳
            info.setCreateTime(BigInteger.valueOf(entity.getCreateTime().getTime() / 1000));
        }
        
        info.setIsValid(entity.getIsValid());
        info.setTxHash(entity.getTxHash());
        info.setBlockchainTime(entity.getBlockchainTime());
        info.setImagePath(entity.getImagePath());
        info.setImageName(entity.getImageName());
        info.setImageSize(entity.getImageSize());
        info.setModelName(entity.getModelName());
        info.setPrompt(entity.getPrompt());
        
        return info;
    }
    
    @Override
    public void syncCopyrightData() {
        log.info("开始同步版权数据...");
        // 调用数据同步器 - 执行全量数据同步
        dataSynchronizer.synchronizeAllData();
    }
    
    @Override
    public List<CopyrightInfo> getAllCopyrightsByOwner(String ownerAddress) {
        return getCopyrightsByOwnerFromDB(ownerAddress);
    }
    
    @Override
    public List<CopyrightInfo> getValidCopyrightsByOwner(String ownerAddress) {
        return getValidCopyrightsByOwnerFromDB(ownerAddress);
    }
    
    @Override
    public List<CopyrightTransferEntity> getTransferHistory(BigInteger copyrightId) {
        try {
            CopyrightEntity copyright = copyrightRepository.findByBlockchainId(copyrightId.toString())
                    .orElse(null);
                    
            if (copyright == null) {
                return Collections.emptyList();
            }
            
            return transferRepository.findByCopyrightIdOrderByTransferTimeDesc(copyright.getId());
        } catch (Exception e) {
            log.error("获取转让历史异常: {}", e.getMessage(), e);
            return Collections.emptyList();
        }
    }
    
    @Override
    public List<CopyrightTransferEntity> getTransfersByFromAddress(String address) {
        try {
            return transferRepository.findByFromAddressOrderByTransferTimeDesc(address);
        } catch (Exception e) {
            log.error("获取用户发起的转让记录异常: {}", e.getMessage(), e);
            return Collections.emptyList();
        }
    }
    
    @Override
    public List<CopyrightTransferEntity> getTransfersByToAddress(String address) {
        try {
            return transferRepository.findByToAddressOrderByTransferTimeDesc(address);
        } catch (Exception e) {
            log.error("获取用户接收的转让记录异常: {}", e.getMessage(), e);
            return Collections.emptyList();
        }
    }
    
    @Override
    public CopyrightInfo getCopyrightFromDB(BigInteger id) {
        try {
            return copyrightRepository.findByBlockchainId(id.toString())
                    .map(this::convertEntityToInfo)
                    .orElse(null);
        } catch (Exception e) {
            log.error("从数据库获取版权信息异常: {}", e.getMessage(), e);
            return null;
        }
    }
    
    @Override
    public BigInteger createCertificate(String address, String imageHash, MultipartFile file, 
                                       String imageName, String modelName, String prompt) {
        // 创建版权 - 调用内部方法处理基础版权创建逻辑
        BigInteger copyrightId = createCopyrightInternal(address, imageHash);
        
        try {
            // 保存图片文件 - 将上传的图片保存到指定目录
            String imagePath = CopyrightUtils.saveImageFile(file, 
                CopyrightUtils.getUploadDirectory(address, copyrightId.toString()));
            
            // 同步元数据 - 将图片相关的元数据保存到数据库
            dataSynchronizer.syncCopyrightMetadata(
                copyrightId,
                imagePath,
                imageName != null ? imageName : file.getOriginalFilename(),
                file.getSize(),
                modelName,
                prompt
            );
            
            return copyrightId;
        } catch (Exception e) {
            log.error("创建版权存证异常: {}", e.getMessage(), e);
            throw new RuntimeException("创建版权存证失败: " + e.getMessage(), e);
        }
    }
    
    @Override
    public List<CopyrightInfo> getValidCopyrightsByHash(String imageHash) {
        try {
            return copyrightRepository.findByImageHashAndIsValidTrueOrderByCreateTimeDesc(imageHash)
                    .stream()
                    .map(this::convertEntityToInfo)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("获取有效的哈希版权列表异常: {}", e.getMessage(), e);
            return Collections.emptyList();
        }
    }
    
    @Override
    public CopyrightInfo createCertificateAndGetInfo(String address, String imageName, String modelName, 
                                           String prompt, MultipartFile file) throws Exception {
        // 计算图片哈希 - 使用工具类计算上传图片的唯一哈希值
        String imageHash = CopyrightUtils.calculateImageHash(file);
        if (imageHash == null) {
            throw new IllegalArgumentException("无法计算图片哈希值");
        }
        
        // 创建版权存证 - 调用创建证书方法处理核心逻辑
        BigInteger copyrightId = createCertificate(address, imageHash, file, imageName, modelName, prompt);
        
        // 获取完整版权信息 - 从数据库获取最新创建的版权信息
        return getCopyrightFromDB(copyrightId);
    }
    
    @Override
    public List<CopyrightTransferInfo> getTransferHistoryInfo(BigInteger copyrightId) {
        List<CopyrightTransferEntity> transfers = getTransferHistory(copyrightId);
        
        return transfers.stream()
                .map(this::convertTransferEntityToInfo)
                .collect(Collectors.toList());
    }
    
    @Override
    public List<CopyrightTransferInfo> getTransfersFromUserInfo(String address) {
        List<CopyrightTransferEntity> transfers = getTransfersByFromAddress(address);
        
        return transfers.stream()
                .map(this::convertTransferEntityToInfo)
                .collect(Collectors.toList());
    }
    
    @Override
    public List<CopyrightTransferInfo> getTransfersToUserInfo(String address) {
        List<CopyrightTransferEntity> transfers = getTransfersByToAddress(address);
        
        return transfers.stream()
                .map(this::convertTransferEntityToInfo)
                .collect(Collectors.toList());
    }
    
    /**
     * 转换转让实体为信息对象
     */
    private CopyrightTransferInfo convertTransferEntityToInfo(CopyrightTransferEntity entity) {
        if (entity == null) {
            return null;
        }
        
        // 创建转让信息对象 - 使用静态工厂方法从实体创建信息对象
        CopyrightTransferInfo info = CopyrightTransferInfo.fromEntity(entity);
        
        try {
            // 关联版权信息 - 获取并关联相关的版权详细信息
            CopyrightEntity copyright = copyrightRepository.findById(entity.getCopyrightId())
                    .orElse(null);
            if (copyright != null) {
                info.setBlockchainId(copyright.getBlockchainId());
                // 将实体转换为信息对象 - 调用转换方法处理实体到信息对象的映射
                info.setCopyrightInfo(convertEntityToInfo(copyright));
            }
        } catch (Exception e) {
            log.error("加载关联版权信息失败: {}", e.getMessage());
        }
        
        return info;
    }
    
    @Override
    public Map<String, Object> verifyImageCopyright(MultipartFile file) throws Exception {
        // 计算图片哈希 - 使用工具类计算上传图片的唯一哈希值
        String imageHash = CopyrightUtils.calculateImageHash(file);
        // 根据哈希验证版权 - 调用哈希验证方法处理核心验证逻辑
        return verifyByHash(imageHash);
    }
    
    @Override
    public Map<String, Object> verifyByHash(String imageHash) {
        Map<String, Object> result = new HashMap<>();
        result.put("imageHash", imageHash);
        
        try {
            List<CopyrightInfo> copyrights = getValidCopyrightsByHash(imageHash);
            
            boolean hasValid = !copyrights.isEmpty();
            result.put("exists", hasValid);
            
            if (hasValid) {
                CopyrightInfo latestCopyright = copyrights.get(0);
                result.put("copyright", latestCopyright);
                result.put("owner", latestCopyright.getOwnerAddress());
                result.put("createTime", latestCopyright.getCreateTime());
                
                List<CopyrightTransferInfo> transferHistory = getTransferHistoryInfo(
                        new BigInteger(latestCopyright.getBlockchainId()));
                result.put("transferHistory", transferHistory);
            }
        } catch (Exception e) {
            log.error("验证版权失败: {}", e.getMessage(), e);
            result.put("exists", false);
            result.put("error", e.getMessage());
        }
        
        return result;
    }
    
    @Override
    public List<CopyrightInfo> getAllCopyrightsFromChain(String address) {
        if (address == null || address.isEmpty()) {
            return Collections.emptyList();
        }
        
        try {
            // 获取用户的版权ID列表 - 调用方法获取所有者的版权ID
            List<BigInteger> copyrightIds = getCopyrightsByOwner(address);
            
            // 获取每个版权的详细信息
            List<CopyrightInfo> result = new ArrayList<>();
            for (BigInteger id : copyrightIds) {
                // 获取版权详情 - 为每个ID查询完整版权信息
                CopyrightInfo info = getCopyright(id);
                if (info != null) {
                    result.add(info);
                }
            }
            
            return result;
        } catch (Exception e) {
            log.error("从区块链获取所有版权详情异常: {}", e.getMessage(), e);
            return Collections.emptyList();
        }
    }
} 